/**
 * 
 */
package truerefactor.genetic;

/**
 * GAParameters - Provides an encapsulation and convenient storage location for
 * all the initialization parameters for the Genetic Algorithm
 * 
 * @author Isaac Griffith
 */
public class GAParameters {

    /**
     * The maximum number of iterations the GA should use prior to completing
     */
    private final int maxIterations;
    /**
     * The probability of mutation
     */
    private final double mutationRate;
    /**
     * Maximum number of alleles to be included in an individual in the GA's
     * population
     */
    private int indMaxSize;
    /**
     * The Maximum Population Size for an iteration of the GA
     */
    private final int popSize;
    /**
     * The factor by which code smell should drop in order to consider the GA
     * complete
     */
    private final double smellFactor;
    /**
     * The maximum number of iterations to output to the log display prior to
     * clearing the display and writing to the log file
     */
    private final int maxLogLength;
    /**
     * The maximum number of metrics used to comprise the total fitness
     */
    private final int maxFitnessSize;

    /**
     * Constructs a new GAParameters class for some Genetic Algorithm
     * 
     * @param maxFitnessSize
     *            The maximum number of fitness metrics to be used by the GA
     * @param maxLogLength
     *            The maximum number of iteragtions to log prior to flushing the
     *            log buffer
     * @param mutationRate
     *            The mutation rate probability
     * @param popSize
     *            The maximum number of individuals in a generation's population
     * @param smellFactor
     *            The maximum percentage of code smells to be removed
     * @param totalLOC
     *            The total LOC of the codebase
     */
    public GAParameters(int maxFitnessSize, int maxLogLength, int maxIterations, double mutationRate, int popSize,
            double smellFactor, int totalLOC)
    {
        this.maxFitnessSize = maxFitnessSize;
        this.maxLogLength = maxLogLength;
        this.mutationRate = (mutationRate > 0.0) ? mutationRate : 0.1;
        this.smellFactor = smellFactor;
        int tMaxIterations = (int) Math.floor(.1 * totalLOC);
        int tPopSize = (int) Math.floor(indMaxSize * totalLOC / 500);

        this.popSize = (popSize > tPopSize) ? popSize : tPopSize;
//        this.maxIterations = (maxIterations > tMaxIterations) ? maxIterations : tMaxIterations;
        this.maxIterations = maxIterations;
        this.indMaxSize = (int) Math.floor(Math.sqrt(maxIterations));
    }

    /**
     * @return the maximum number of iterations to be performed by the GA
     */
    public int getMaxIterations()
    {
        return maxIterations;
    }

    /**
     * @return the probability that a mutation will occur
     */
    public double getMutationRate()
    {
        return mutationRate;
    }

    /**
     * @return the maximum number of refactoring sequences that can comprise and
     *         individual
     */
    public int getIndMaxSize()
    {
        return indMaxSize;
    }

    /**
     * @return the maximum population size for any given generation of the GA
     */
    public int getPopSize()
    {
        return popSize;
    }

    /**
     * @return the maximum percentage of found smells to be removed
     */
    public double getSmellFactor()
    {
        return smellFactor;
    }

    /**
     * @return the maximum number of iterations to log prior to flushing the
     *         buffer
     */
    public int getMaxLogLength()
    {
        return maxLogLength;
    }

    /**
     * @return the Maximum number of metrics to comprise the fitness of any
     *         individual
     */
    public int getMaxFitnessSize()
    {
        return maxFitnessSize;
    }

    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();

        sb.append("\tIndividual Max Size: " + indMaxSize + "\n");
        sb.append("\tMax Fitness Size: " + maxFitnessSize + "\n");
        sb.append("\tMax Iterations: " + maxIterations + "\n");
        sb.append("\tMax Log Length: " + maxLogLength + "\n");
        sb.append("\tPopulation Size: " + popSize + "\n");
        sb.append("\tSmell Factor: " + smellFactor + "\n");
        sb.append("\tMutation Rate: " + mutationRate + "\n");

        return sb.toString();
    }

    /**
     * Sets the maximum number of refactoring sequences that can comprise an
     * individual to the provided value.
     * 
     * @param d
     *            new maximum number of refactoring sequences for any
     *            individual.
     */
    public void setIndMaxSize(int d)
    {
        this.indMaxSize = d;
    }
}
